<ParseChildren(True, "Items")> _
Public Class Validator
    Inherits WebControls.Panel
    Implements IJObjective

    Private m_sNamespace As String
    Private m_sPropertyName As String
    Private m_sConstructor As String
    Private m_sDataID As String

    Private m_iOperator As Operators = Operators.And

    Private m_lstItemsToValidate As New List(Of ItemToValidate)
    Private m_lstControlsToValidate As New List(Of ControlToValidate)
    Private m_ctlMessageLabel As New Label
    Private m_sbChildValidators As New Text.StringBuilder

    Private Structure ControlToValidate
        Public Control As IJObjective
        Public Item As ItemToValidate
    End Structure

    Public Enum Types
        <System.ComponentModel.Description("jObjective.Validate.Custom")> Custom
        <System.ComponentModel.Description("jObjective.Validate.ContactNumber")> ContactNumber
        <System.ComponentModel.Description("jObjective.Validate.Email")> Email
        <System.ComponentModel.Description("jObjective.Validate.Currency")> Currency
        <System.ComponentModel.Description("jObjective.Validate.Number")> Number
        <System.ComponentModel.Description("jObjective.Validate.Postcode")> Postcode
        <System.ComponentModel.Description("jObjective.Validate.Date")> [Date]
        <System.ComponentModel.Description("jObjective.Validate.Time")> Time
        <System.ComponentModel.Description("jObjective.Validate.RequiredReference")> RequiredReference
        <System.ComponentModel.Description("jObjective.Validate.RequiredString")> RequiredString
        <System.ComponentModel.Description("jObjective.Validate.RequiredHTML")> RequiredHTML
        <System.ComponentModel.Description("jObjective.Validate.RequiredContactNumber")> RequiredContactNumber
        'RequiredContactNumbers
        <System.ComponentModel.Description("jObjective.Validate.RequiredEmail")> RequiredEmail
        <System.ComponentModel.Description("jObjective.Validate.RequiredCurrency")> RequiredCurrency
        <System.ComponentModel.Description("jObjective.Validate.RequiredNumber")> RequiredNumber
        <System.ComponentModel.Description("jObjective.Validate.RequiredPostcode")> RequiredPostcode
        <System.ComponentModel.Description("jObjective.Validate.RequiredDate")> RequiredDate
        <System.ComponentModel.Description("jObjective.Validate.RequiredDropDown")> RequiredDropDown
        'RequiredRadioGroup
        <System.ComponentModel.Description("jObjective.Validate.RequiredCheckbox")> RequiredCheckbox
        'RequiredCardDate
        'RequiredExpiryDate
        <System.ComponentModel.Description("jObjective.Validate.RequiredAddressRef")> RequiredAddressRef
        <System.ComponentModel.Description("jObjective.Validate.RequiredCV2")> RequiredCV2
        <System.ComponentModel.Description("jObjective.Validate.HiddenField")> HiddenField
        <System.ComponentModel.Description("jObjective.Validate.RequiredTime")> RequiredTime
    End Enum

    Public Enum Operators
        [And]
        [Or]
    End Enum

    Public Property [Operator]() As Operators
        Get
            Return m_iOperator
        End Get
        Set(ByVal value As Operators)
            m_iOperator = value
        End Set
    End Property

    Public Property [Namespace]() As String Implements IJObjective.Namespace
        Get
            Return m_sNamespace
        End Get
        Set(ByVal value As String)
            m_sNamespace = value
        End Set
    End Property

    Public Property ObjectName() As String Implements IJObjective.ObjectName
        Get
            Return m_sPropertyName
        End Get
        Set(ByVal value As String)
            m_sPropertyName = value
        End Set
    End Property

    Public Property Constructor() As String Implements IJObjective.Constructor
        Get
            Return m_sConstructor
        End Get
        Set(ByVal value As String)
            m_sConstructor = value
        End Set
    End Property

    Public Property DataID() As String Implements IJObjective.DataID
        Get
            Return m_sDataID
        End Get
        Set(ByVal value As String)
            m_sDataID = value
        End Set
    End Property

    Public Property Text() As String
        Get
            Return m_ctlMessageLabel.InnerHtml
        End Get
        Set(ByVal value As String)
            m_ctlMessageLabel.InnerHtml = value
        End Set
    End Property

    <PersistenceMode(PersistenceMode.InnerDefaultProperty)> _
    Public ReadOnly Property Items() As List(Of ItemToValidate)
        Get
            Return m_lstItemsToValidate
        End Get
    End Property

    Public Overrides ReadOnly Property ClientID() As String
        Get
            Return ID
        End Get
    End Property

    Public Sub New()
        DataID = Common.GetUniqueID(Context)
    End Sub

    Protected Overrides Sub CreateChildControls()
        MyBase.CreateChildControls()

        With m_ctlMessageLabel
            .ID = Common.GetUniqueID(Context)
            .Style("display") = "none"
        End With

        Controls.AddAt(0, m_ctlMessageLabel)

        ChildControlsCreated = True
    End Sub

    Private Sub Validator_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
        EnsureChildControls()

        Dim sbConstructor As New Text.StringBuilder

        With sbConstructor
            .Append("new jObjective.Validator(null,null,$('#")
            .Append(m_ctlMessageLabel.ID)
            .Append("'),jObjective.")
            .Append([Operator].ToString())
            .Append("Operator)")
        End With

        m_sConstructor = sbConstructor.ToString()

        For Each objItemToValidate As ItemToValidate In Items
            Dim objControl As IJObjective = Me.FindControl(objItemToValidate.Control)

            Dim objControlToValidate As New ControlToValidate

            With objControlToValidate
                .Control = objControl
                .Item = objItemToValidate
            End With

            m_lstControlsToValidate.Add(objControlToValidate)
        Next
    End Sub

    Private Sub Validator_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        ID = DataID
    End Sub

    Private Sub Validator_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
        Dim iCount As Integer = 0
        With m_sbChildValidators
            For Each objControl As ControlToValidate In m_lstControlsToValidate
                .Append([Namespace])
                .Append(".Item")
                .Append(iCount)
                .Append("=new jObjective.Validator(")
                .Append(objControl.Control.Namespace)
                .Append(",")
                If objControl.Item.Type = Types.Custom Then
                    .Append(objControl.Item.ClientFunction)
                Else
                    .Append(Common.GetEnumDescription(objControl.Item.Type))
                End If
                .Append(",$('#")
                .Append(m_ctlMessageLabel.ID)
                .Append("'),jObjective.")
                .Append([Operator].ToString())
                .AppendLine("Operator);")

                iCount += 1
            Next
        End With

        ScriptManager.RegisterStartupScript(Me, Me.GetType, ID, m_sbChildValidators.ToString(), True)
    End Sub
End Class

<ControlBuilder(GetType(ItemToValidateBuilder))> _
Public Class ItemToValidate
    Implements IAttributeAccessor

    Private m_objAttributes As AttributeCollection = Nothing
    Private m_sClientEnhancedControl As String
    Private m_iType As Validator.Types
    Private m_sClientFunction As String

    <PersistenceMode(PersistenceMode.Attribute), IDReferenceProperty(GetType(IJObjective)), ComponentModel.TypeConverter(GetType(WebControls.ControlIDConverter))> _
    Public Property Control() As String
        Get
            Return m_sClientEnhancedControl
        End Get
        Set(ByVal value As String)
            m_sClientEnhancedControl = value
        End Set
    End Property

    <PersistenceMode(PersistenceMode.Attribute)> _
    Public Property Type() As Validator.Types
        Get
            Return m_iType
        End Get
        Set(ByVal value As Validator.Types)
            m_iType = value
        End Set
    End Property

    <PersistenceMode(PersistenceMode.Attribute)> _
    Public Property ClientFunction() As String
        Get
            Return m_sClientFunction
        End Get
        Set(ByVal value As String)
            m_sClientFunction = value
        End Set
    End Property

    <ComponentModel.Browsable(False), ComponentModel.DesignerSerializationVisibility(ComponentModel.DesignerSerializationVisibility.Hidden)> _
    Public ReadOnly Property Attributes() As AttributeCollection
        Get
            If (Me.m_objAttributes Is Nothing) Then
                Me.m_objAttributes = New AttributeCollection(New StateBag(True))
            End If
            Return Me.m_objAttributes
        End Get
    End Property

    Public Function GetAttribute(ByVal key As String) As String Implements System.Web.UI.IAttributeAccessor.GetAttribute
        Return Me.Attributes.Item(key)
    End Function

    Public Sub SetAttribute(ByVal key As String, ByVal value As String) Implements System.Web.UI.IAttributeAccessor.SetAttribute
        Me.Attributes.Item(key) = value
    End Sub
End Class

Public Class ItemToValidateBuilder
    Inherits ControlBuilder

End Class